// ------------------------------------------------------------------------------
// This partial class was auto-generated for use with the Habanero Architecture.
// NB Custom code should be placed in the provided stub class.
// Please do not modify this class directly!
//
// If tests are failing due to a unique condition in your application, use the
// ignore feature in the stub class SetupTestFixture() method.  Reimplement the
// test in the stub class.
// ------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Diagnostics;
using <<|=BOPROJECTNAME|>>;
using Habanero.Base;
using Habanero.BO;
using Habanero.BO.ClassDefinition;
using NUnit.Framework;
using Habanero.Testability;

namespace <<|=BOTestProjectName|>>
{
// ReSharper disable InconsistentNaming
// ReSharper disable RedundantNameQualifier
// ReSharper disable SuggestUseVarKeywordEvident

    // Provides the part of the test class that tests <<|=CLASSNAME|>> objects
    [TestFixture]
    public partial class Test<<|=CLASSNAME|>>
    {
        private readonly Dictionary<string, string> _ignoreList = new Dictionary<string, string>();

        <<|-- This could be improved if SetUp knew which test method was being setup, but it doesn't --|>>
        /// <summary>
        /// Checks if the developer has put this test on the ignore list.
        /// If your application has a unique condition that is causing a
        /// generated test to fail, you would lose test repairs when this
        /// class is regenerated.
        /// Simply add the test name to the ignore list in the TestFixtureSetup
        /// of the once-off-generated part of this test class, and then
        /// reimplement the test in that class.
        /// </summary>
        private void CheckIfTestShouldBeIgnored()
        {
            string methodName = new StackTrace().GetFrame(1).GetMethod().Name;
            if (_ignoreList.ContainsKey(methodName))
            {
                Assert.Ignore("The developer has chosen to ignore this test: " + methodName +
                    ", Reason: " + _ignoreList[methodName]);
            }
        }
        
        [Test]  // Ensures that the defaults have not been tampered
        public void Test_Create<<|=CLASSNAME|>>WithDefaults()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = new <<|=CLASSNAME|>>();

            //---------------Test Result -----------------------
            <<| FOREACH(AllProperties):
            <<|IF(GenerateCode):
            <<| IF(!InheritanceType EQUALS "SingleTableInheritance"):<<|-- STI Eliminates the ID prop --|>>
            <<| IF(Property_HasDefaultValue):
            <<|-- nullable types must have a .Value --|>>
            Assert.IsNotNull(<<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>>);
            Assert.IsInstanceOf(<<|=#CLASSNAME|>>.Props["<<|=PROPERTYNAME|>>"].PropertyType, <<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>>);
            <<|-- Is there a way to test the actual values, surely they're random? --|>>
            |>>
            <<| IF(!Property_HasDefaultValue):
            Assert.IsNull(<<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>>);
            |>>
            |>>
            |>>
            |>>
        }
		
	    /// <summary>
		/// Ensures that a class can be successfully saved
		/// </summary>
        [Test]  
        public void Test_Save<<|=CLASSNAME|>>()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = TestUtils<<|=CLASSNAME|>>.CreateUnsavedValid<<|=CLASSNAME|>>();

            //---------------Assert Precondition----------------
            Assert.IsTrue(<<|=#CLASSNAME|>>.Status.IsNew);
            BusinessObjectCollection<<<|=CLASSNAME|>>> col = new BusinessObjectCollection<<<|=CLASSNAME|>>>();
            col.LoadAll();
            Assert.AreEqual(0, col.Count);

            //---------------Execute Test ----------------------
            <<|=#CLASSNAME|>>.Save();

            //---------------Test Result -----------------------
            Assert.IsFalse(<<|=#CLASSNAME|>>.Status.IsNew);
            col.LoadAll();
            Assert.AreEqual(1, col.Count);
	    
            <<|-- TODO: Clear object manager. ? --|>>
        }

		 /// <summary>
		 /// Ensures that a saved class can be loaded
		 /// </summary>
        [Test] 
        public void Test_Load<<|=CLASSNAME|>>()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = TestUtils<<|=CLASSNAME|>>.CreateSaved<<|=CLASSNAME|>>();

            //---------------Execute Test ----------------------
            <<|=CLASSNAME|>> loaded<<|=CLASSNAME|>> = Broker.GetBusinessObject<<<|=CLASSNAME|>>>(<<|=#CLASSNAME|>>.ID);

            //---------------Test Result -----------------------
            <<|FOREACH(AllProperties):
            <<|IF(GenerateCode):
            <<|IF(!InheritanceType EQUALS "SingleTableInheritance"):<<|-- STI Eliminates the ID prop --|>>
            Assert.AreEqual(<<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>>, loaded<<|=CLASSNAME|>>.<<|=PROPERTYNAME|>>);
            |>>
            |>>
            |>>
        }
        
	     /// <summary>
		 /// Ensures that a class can be deleted
		 /// </summary>
        [Test] 
        public void Test_Delete<<|=CLASSNAME|>>()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = TestUtils<<|=CLASSNAME|>>.CreateSaved<<|=CLASSNAME|>>();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            <<|=#CLASSNAME|>>.MarkForDelete();
            <<|=#CLASSNAME|>>.Save();
            //---------------Test Result -----------------------
            try
            {
            Broker.GetBusinessObject<<<|=CLASSNAME|>>>(<<|=#CLASSNAME|>>.ID);
            Assert.Fail("expected Err");
            }
            catch (BusObjDeleteConcurrencyControlException ex)
            {
                StringAssert.Contains("A Error has occured since the object you are trying to refresh has been deleted by another user", ex.Message);
                StringAssert.Contains("There are no records in the database for the Class: <<|=CLASSNAME|>>", ex.Message);
            }
        }

		 /// <summary>
		 /// Ensures that updates to property values are stored and can be retrieved
		 /// </summary>
        [Test] 
        public void Test_Update<<|=CLASSNAME|>>()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = TestUtils<<|=CLASSNAME|>>.CreateSaved<<|=CLASSNAME|>>();
		    BOTestFactory<<<|=CLASSNAME|>>> factory = TestUtils<<|=CLASSNAME|>>.GetTestFactory();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            <<|FOREACH(AllProperties):
            <<|IF(!Property_IsClassID):
            <<|IF(!ReadWriteRule EQUALS "WriteNew"):
            <<|IF(!ReadWriteRule EQUALS "ReadOnly"):
			<<|IF(!ReadWriteRule EQUALS "WriteOnce"):
            <<|IF(GenerateCode):
            var valueFor<<|=PROPERTYNAME|>> = <<|=VALIDVALUE|>>;
            <<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>> = valueFor<<|=PROPERTYNAME|>>;
            |>>
            |>>
            |>>
            |>>
            |>>
			|>>
            <<|=#CLASSNAME|>>.Save();

            //---------------Test Result -----------------------
            BusinessObjectManager.Instance.ClearLoadedObjects();
            GC.Collect();
            TestUtilsShared.WaitForGC();
            <<|=CLASSNAME|>> retrieved<<|=CLASSNAME|>> =
                    Broker.GetBusinessObject<<<|=CLASSNAME|>>>(<<|=#CLASSNAME|>>.ID);
            
            <<|FOREACH(AllProperties):
            <<|IF(!Property_IsClassID):
            <<|IF(GenerateCode):
            <<|IF(!ReadWriteRule EQUALS "WriteNew"):
            <<|IF(!ReadWriteRule EQUALS "ReadOnly"):
			<<|IF(!ReadWriteRule EQUALS "WriteOnce"):
            Assert.AreEqual(valueFor<<|=PROPERTYNAME|>>, retrieved<<|=CLASSNAME|>>.<<|=PROPERTYNAME|>>);
            |>>
            |>>
            |>>
            |>>
            |>>
			|>>
        }
        
		 /// <summary>
		 /// Ensures that gets and sets in the code refer to the same property
		 /// </summary>
        [Test] 
        public void Test_PropertyGetters()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = new <<|=CLASSNAME|>>();
            BOTestFactory<<<|=CLASSNAME|>>> factory = BOTestFactoryRegistry.Instance.Resolve<<<|=CLASSNAME|>>>();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            <<|FOREACH(AllProperties):
            <<|IF(!Property_IsClassID):
            <<|IF(GenerateCode):
            var valueFor<<|=PROPERTYNAME|>> = factory.GetValidPropValue(<<|=#CLASSNAME|>>properties=><<|=#CLASSNAME|>>properties.<<|=PROPERTYNAME|>>);          
            <<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>> = valueFor<<|=PROPERTYNAME|>>;
            |>>
            |>>
            |>>
            
            //---------------Test Result -----------------------
            <<|FOREACH(AllProperties):
            <<|IF(!Property_IsClassID):
            <<|IF(GenerateCode):
            Assert.AreEqual(valueFor<<|=PROPERTYNAME|>>, <<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>>);
            |>>
            |>>
            |>>
        }
        
		 /// <summary>
		 /// Ensures that property getters in the code point to the correct property
		 /// </summary>
        [Test] 
        public void Test_PropertyGettersUseCorrectPropertyNames()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = new <<|=CLASSNAME|>>();
            BOTestFactory<<<|=CLASSNAME|>>> factory = BOTestFactoryRegistry.Instance.Resolve<<<|=CLASSNAME|>>>();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            <<|FOREACH(Properties):
            <<|IF(!Property_IsClassID):
            <<|IF(GenerateCode):
            var valueFor<<|=PROPERTYNAME|>> = <<|=VALIDVALUE|>>;
            <<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>> = valueFor<<|=PROPERTYNAME|>>;
            |>>
            |>>
            |>>
            
            //---------------Test Result -----------------------
            <<|FOREACH(Properties):
            <<|IF(!Property_IsClassID):
            <<|IF(GenerateCode):
            Assert.AreEqual(valueFor<<|=PROPERTYNAME|>>, <<|=#CLASSNAME|>>.GetPropertyValue("<<|=PROPERTYNAME|>>"));
            |>>
            |>>
            |>>
        }
        
		 /// <summary>
		 /// Ensures that property setters in the code point to the correct property
		 /// </summary>
        [Test]  
        public void Test_PropertySettersUseCorrectPropertyNames()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = new <<|=CLASSNAME|>>();
            BOTestFactory<<<|=CLASSNAME|>>> factory = BOTestFactoryRegistry.Instance.Resolve<<<|=CLASSNAME|>>>();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            <<|FOREACH(Properties):
            <<|IF(!Property_IsClassID):
            <<|IF(GenerateCode):
		   	var valueFor<<|=PROPERTYNAME|>> = factory.GetValidPropValue(<<|=#CLASSNAME|>>properties=><<|=#CLASSNAME|>>properties.<<|=PROPERTYNAME|>>);          
            <<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>> = valueFor<<|=PROPERTYNAME|>>;
            |>>
            |>>
            |>>
            
            //---------------Test Result -----------------------
            <<|FOREACH(Properties):
            <<|IF(!Property_IsClassID):
            <<|IF(GenerateCode):
            Assert.AreEqual(valueFor<<|=PROPERTYNAME|>>, <<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>>);
            |>>
            |>>
            |>>
        }
        
		 <<|IF(!HasCompulsoryProperties):
		  /// <summary>
		 /// Makes sure there are no non-null rules in the database that don't have corresponding compulsory rules
		 /// </summary>
        [Test]  
        public void Test_SetPropertyValue_Null()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = TestUtils<<|=CLASSNAME|>>.CreateSaved<<|=CLASSNAME|>>();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            <<|FOREACH(Properties):
            <<|IF(!ISCOMPULSORY):
            <<|IF(!Property_IsClassID):
            <<|IF(GenerateCode):
            <<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>> = null;
            |>>
            |>>
            |>>
            |>>
            <<|=#CLASSNAME|>>.Save();

            //---------------Test Result -----------------------
            BusinessObjectManager.Instance.ClearLoadedObjects();
            GC.Collect();
            TestUtilsShared.WaitForGC();
            <<|=CLASSNAME|>> retrieved<<|=CLASSNAME|>> =
                    Broker.GetBusinessObject<<<|=CLASSNAME|>>>(<<|=#CLASSNAME|>>.ID);
            
            <<|FOREACH(Properties):
            <<|IF(!ISCOMPULSORY):
            <<|IF(!Property_IsClassID):
            <<|IF(GenerateCode):
            Assert.IsNull(retrieved<<|=CLASSNAME|>>.<<|=PROPERTYNAME|>>);
            |>>
            |>>
            |>>
            |>>
        }
        |>>
        
		 /// <summary>
		 /// Tests that giving a property an invalid type causes an error
		 /// </summary>
		 <<|-- TODO
        [Test] 
        public void Test_InvalidPropertyTypeThrowsException()
        {
            // How would you write this test?
        }
        |>>
        [Test]
        public void Test_NotSettingCompulsoryPropertiesThrowsException()
        {
            CheckIfTestShouldBeIgnored();
            <<|IF(Class_HasCompulsoryProperties):
            //---------------Set up test pack-------------------
            BORegistry.DataAccessor = new DataAccessorInMemory();
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = TestUtils<<|=CLASSNAME|>>.CreateUnsavedValid<<|=CLASSNAME|>>();

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            <<|FOREACH(AllProperties):
            <<|IF(GenerateCode):
            <<|IF(IsCompulsory):
            <<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>> = null;
            |>>
            |>>
            |>>
            
            try
            {
                <<|=#CLASSNAME|>>.Save();
                Assert.Fail("Should throw an exception when compulsory properties are null");
            }
            //---------------Test Result -----------------------
            catch (BusObjectInAnInvalidStateException ex)
            {
                <<|FOREACH(AllProperties):
                <<|IF(IsCompulsory):
                StringAssert.Contains(".<<|=DISPLAYNAME|>>' is a compulsory field and has no value", ex.Message);
                |>>
                |>>
            }
            |>>
            <<|IF(!Class_HasCompulsoryProperties):// There are no compulsory properties|>>
        }
        
		/// <summary>
		/// Checks that the read-write rules have not been changed in the class defs
		/// </summary>
        [Test]  
        public void Test_ReadWriteRules()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            ClassDef classDef = ClassDef.Get<<<|=CLASSNAME|>>>();

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            
            //---------------Test Result -----------------------
            <<|FOREACH(AllProperties):
            <<|IF(GenerateCode):
			Assert.AreEqual("<<|=READWRITERULE|>>",classDef.PropDefColIncludingInheritance["<<|=PROPERTYNAME|>>"].ReadWriteRule.ToString());
            |>>
            |>>
        }
        
        <<|-- TODO --------------------------------------------------------------------
         /// <summary>
		 /// Tests that the expected lookup list values are available to the user
		 /// </summary>
        [Test]  
        public void Test_SimpleLookupList_ValuesCorrect()
        {
            // Cycle through properties, if prop is a simplelookuplist type, then:
            //   Get lookup list values from BO
            //   Build expected list using combination of pipe-separated option list
            //     and item key pairs
            // Sort alphabetically and compare count and content
            
            // This test deals with the possibility that the classdefs file could have been meddled with
        }

		 /// <summary>
		 /// Tests that the attributes of the lookup list are intact (can't predict the actual content)
		 /// </summary>
        [Test]  
        public void Test_BusinessObjectLookupList_ValuesCorrect()
        {
            // Write tests to check that the classdefs have not been meddled with
        }
        
		 /// <summary>
		 /// Tests that the attributes of the lookup list are intact (can't predict the actual content)
		 /// </summary>
        [Test]  
        public void Test_DatabaseLookupList_ValuesCorrect()
        {
            // Write tests to check that the classdefs have not been meddled with
        }
        ------------------------------------------------------------------------- --|>>        

		   <<|-- TODO: Firestarter needs to set an ID primary key prop as WriteOnce
		 /// <summary>
		 /// Test that an ID property has been created as write-once by Firestarter, if there are any ID properties
		 /// </summary>
        [Test]  
        public void Test_IDPropertyIsWriteOnce()
        {
            CheckIfTestShouldBeIgnored();
            <<|IF(HasPrimaryKeyWithProps):
            <<|IF(PrimaryKeyIsID):
            //---------------Set up test pack-------------------
            ClassDef classDef = ClassDef.Get<<<|=CLASSNAME|>>>();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            //---------------Test Result -----------------------           
            <<|FOREACH(PrimaryKeyProperties):
            Assert.AreEqual("WriteOnce", classDef.PropDefcol["<<|=PROPERTYNAME|>>"].ReadWriteRule.ToString());
            |>>
            |>>
            <<|IF(!PrimaryKeyIsID):// Test does not apply to this class since the primary key is not an ID|>>
            |>>
            <<|IF(!HasPrimaryKeyWithProps):// Test does not apply to this class since there is no primary key defined|>>
        }
        --|>>
        
        <<|-- TODO: put this back in when duplicates checked in inmemory
	     /// <summary>
		 /// Checks that a BO with the same ID cannot be saved
		 /// </summary>
        [Test]  
        public void Test_NoDuplicate<<|=CLASSNAME|>>_DueToDuplicateID()
        {
            CheckIfTestShouldBeIgnored();
            <<|IF(HasPrimaryKeyWithProps):
            <<|IF(PrimaryKeyIsID):
            //---------------Set up test pack-------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = TestUtils<<|=CLASSNAME|>>.CreateSaved<<|=CLASSNAME|>>();
            
            //---------------Execute Test ----------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>>Duplicate = TestUtils<<|=CLASSNAME|>>.CreateUnsavedValid<<|=CLASSNAME|>>();
            <<|FOREACH(PrimaryKeyProperties):
            <<|=#CLASSNAME|>>Duplicate.<<|=PROPERTYNAME|>> = <<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>>;
            |>>
            try
            {
                <<|=#CLASSNAME|>>Duplicate.Save();
                Assert.Fail("Should raise err");
            }
            //---------------Test Result -----------------------
            catch (Exception ex)
            {
                // Error message may differ depending on where it is thrown
                //StringAssert.Contains("A '<<|=CLASSNAME|>>' already exists with the same identifier:", ex.Message);
            }
            |>>
            <<|IF(!PrimaryKeyIsID):// Test does not apply to this class since the primary key is not an ID|>>
            |>>
            <<|IF(!HasPrimaryKeyWithProps):// Test does not apply to this class since there is no primary key defined|>>
        }
        --|>>
		 /// <summary>
		 /// Checks that classes using primary keys that are not an ID cannot have duplicate primary key values
		 /// </summary>
        [Test] 
        public void Test_NonObjectIDPrimaryKey_ChecksForUniqueness()
        {
            CheckIfTestShouldBeIgnored();
            <<|IF(HasPrimaryKeyWithProps):
            <<|IF(!PrimaryKeyIsID):
            //---------------Set up test pack-------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = TestUtils<<|=CLASSNAME|>>.CreateSaved<<|=CLASSNAME|>>();
            
            //---------------Execute Test ----------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>>Duplicate = TestUtils<<|=CLASSNAME|>>.CreateUnsavedValid<<|=CLASSNAME|>>();
            <<|FOREACH(PrimaryKeyProperties):
            <<|=#CLASSNAME|>>Duplicate.<<|=PROPERTYNAME|>> = <<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>>;
            |>>
            try
            {
                <<|=#CLASSNAME|>>Duplicate.Save();
                Assert.Fail("Should raise err");
            }
            //---------------Test Result -----------------------
            catch (BusObjDuplicateConcurrencyControlException ex)
            {
                StringAssert.Contains("A '<<|=DISPLAYNAME|>>' already exists with the same identifier:", ex.Message);
            }
            |>>
            <<|IF(PrimaryKeyIsID):// Test does not apply to this class since the primary key is an ID|>>
            |>>
            <<|IF(!HasPrimaryKeyWithProps):// Test does not apply to this class since there is no primary key defined|>>
        }
        
        <<|-- TODO: put these two tests back in when inmemory working
        <<|FOREACH(AlternateKeys):
        [Test, Ignore("Duplicate check not yet implemented for inmemory")]  // Checks that the alternate key is enforced and hasn't been tampered with in the class defs
        public void Test_PropertiesInAlternateKeys_ChecksForUniqueness_<<|=KEYNAME|>>()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = TestUtils<<|=CLASSNAME|>>.CreateSaved<<|=CLASSNAME|>>();
            
            //---------------Execute Test ----------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>>Duplicate = TestUtils<<|=CLASSNAME|>>.CreateUnsavedValid<<|=CLASSNAME|>>();
            <<|FOREACH(KeyProperties):
            <<|=#CLASSNAME|>>Duplicate.<<|=PROPERTYNAME|>> = <<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>>;
            |>>
            try
            {
                <<|=#CLASSNAME|>>Duplicate.Save();
                Assert.Fail("Should raise err");
            }
            //---------------Test Result -----------------------
            catch (Exception ex)
            {
                StringAssert.Contains("A '<<|=DISPLAYNAME|>>' already exists with the same identifier:", ex.Message);
            }            
        }
        |>>
        
        [Test, Ignore("Duplicate check not yet implemented for inmemor // Checks that duplication is allowed for all properties not in keys (ie. no keys have been set up that weren't expected)
        public void Test_CanHaveDuplicatePropertiesWhenNotInKeys()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = TestUtils<<|=CLASSNAME|>>.CreateSaved<<|=CLASSNAME|>>();
            
            //---------------Execute Test ----------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>>Duplicate = TestUtils<<|=CLASSNAME|>>.CreateUnsavedValid<<|=CLASSNAME|>>();
            <<|FOREACH(AllProperties):
            <<|IF(!Property_IsInKey):
            <<|=#CLASSNAME|>>Duplicate.<<|=PROPERTYNAME|>> = <<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>>;
            |>>
            |>>
            try
            {
                <<|=#CLASSNAME|>>Duplicate.Save();
                
            //---------------Test Result -----------------------
                Assert.IsFalse(<<|=#CLASSNAME|>>Duplicate.Status.IsNew);
                Assert.IsFalse(<<|=#CLASSNAME|>>Duplicate.Status.IsDirty);
            }
            catch (Exception ex)
            {
                Assert.Fail("Properties not in keys should allow duplicates");
            }            
        }
        --|>>
        <<|FOREACH(Relationships):
        <<|IF(GenerateCode):
        <<|IF(!IsMultiple):
	     /// <summary>
		 /// Checks that BOs in a single relationship load correctly (no tampering with class defs)
		 /// </summary>
        [Test]  
        public void Test_LoadThroughSingleRelationship_<<|=RELATIONSHIPNAME|>>()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            BORegistry.DataAccessor = new DataAccessorInMemory();
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = TestUtils<<|=CLASSNAME|>>.CreateUnsavedValid<<|=CLASSNAME|>>();
            
            <<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>> boForRelationship<<|=RELATIONSHIPNAME|>> = TestUtils<<|=RELATEDCLASS|>>.CreateUnsavedValid<<|=RELATEDCLASS|>>();
			<<|=#CLASSNAME|>>.<<|=RELATIONSHIPNAME|>> = boForRelationship<<|=RELATIONSHIPNAME|>>;
			<<|=#CLASSNAME|>>.Save();
            boForRelationship<<|=RELATIONSHIPNAME|>>.Save();
			
            BusinessObjectManager.Instance.ClearLoadedObjects();
            GC.Collect();
            TestUtilsShared.WaitForGC();
            //---------------Execute Test ----------------------
            <<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>> loadedRelatedBO = Broker.GetBusinessObject<<<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>>>(boForRelationship<<|=RELATIONSHIPNAME|>>.ID);
            <<|=CLASSNAME|>> loaded<<|=CLASSNAME|>> = Broker.GetBusinessObject<<<|=CLASSNAME|>>>(<<|=#CLASSNAME|>>.ID);
            //---------------Test Result -----------------------
            Assert.AreEqual(boForRelationship<<|=RELATIONSHIPNAME|>>, loaded<<|=CLASSNAME|>>.<<|=RELATIONSHIPNAME|>>);
            Assert.AreEqual(loadedRelatedBO, loaded<<|=CLASSNAME|>>.<<|=RELATIONSHIPNAME|>>);
            Assert.AreEqual(loadedRelatedBO, <<|=#CLASSNAME|>>.<<|=RELATIONSHIPNAME|>>);
        }
		|>>
		|>>
        |>>
		        
        <<|FOREACH(Relationships):
        <<|IF(GenerateCode):
        <<|IF(IsMultiple):
	     /// <summary>
		 /// Checks that BOs in a multiple relationship load correctly (no tampering with class defs)
		 /// </summary>
        [Test] 
        public void Test_LoadThroughMultipleRelationship_<<|=RELATIONSHIPNAME|>>()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            BORegistry.DataAccessor = new DataAccessorInMemory();
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = TestUtils<<|=CLASSNAME|>>.CreateSaved<<|=CLASSNAME|>>();

            <<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>> boForRelationship<<|=RELATIONSHIPNAME|>> = TestUtils<<|=RELATEDCLASS|>>.CreateUnsavedValid<<|=RELATEDCLASS|>>();
            boForRelationship<<|=RELATIONSHIPNAME|>>.<<|=RELATEDPROPERTYNAME|>> = <<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>>;
            boForRelationship<<|=RELATIONSHIPNAME|>>.Save();

            BusinessObjectManager.Instance.ClearLoadedObjects();
            GC.Collect();
            TestUtilsShared.WaitForGC();
            //---------------Assert Preconditions---------------
            Assert.AreEqual(1, <<|=#CLASSNAME|>>.<<|=RELATIONSHIPNAME|>>.Count);
            //---------------Execute Test ----------------------
            <<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>> loadedRelatedBO = Broker.GetBusinessObject<<<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>>>(boForRelationship<<|=RELATIONSHIPNAME|>>.ID);
            <<|=CLASSNAME|>> loaded<<|=CLASSNAME|>> = Broker.GetBusinessObject<<<|=CLASSNAME|>>>(<<|=#CLASSNAME|>>.ID);
            //---------------Test Result -----------------------
            Assert.AreEqual(1, loaded<<|=CLASSNAME|>>.<<|=RELATIONSHIPNAME|>>.Count);
            Assert.AreEqual(boForRelationship<<|=RELATIONSHIPNAME|>>, loaded<<|=CLASSNAME|>>.<<|=RELATIONSHIPNAME|>>[0]);
            Assert.AreEqual(loadedRelatedBO, loaded<<|=CLASSNAME|>>.<<|=RELATIONSHIPNAME|>>[0]);
            Assert.AreEqual(loadedRelatedBO, <<|=#CLASSNAME|>>.<<|=RELATIONSHIPNAME|>>[0]);
        }
        |>>
        |>>
        |>>
        
        <<|-- This test template could be combined into the one below if there was an OR function --|>>
        <<|FOREACH(Relationships):
        <<|IF(GenerateCode):
        <<|IF(IsMultiple):
        <<|IF(DeleteParentAction EQUALS "Prevent"):
        [Test]  // Checks that deletion is prevented when a child exists
        public void Test_MultipleRelationshipDeletion_PreventDelete_<<|=RELATIONSHIPNAME|>>()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = TestUtils<<|=CLASSNAME|>>.CreateSaved<<|=CLASSNAME|>>();

            <<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>> boForRelationship<<|=RELATIONSHIPNAME|>> = TestUtils<<|=RELATEDCLASS|>>.CreateUnsavedValid<<|=RELATEDCLASS|>>();
            boForRelationship<<|=RELATIONSHIPNAME|>>.<<|=RELATEDPROPERTYNAME|>> = <<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>>;
            boForRelationship<<|=RELATIONSHIPNAME|>>.Save();

            //---------------Assert Preconditions---------------
            Assert.AreEqual(1, <<|=#CLASSNAME|>>.<<|=RELATIONSHIPNAME|>>.Count);
            IRelationshipDef relationshipDef = ClassDef.Get<<<|=CLASSNAME|>>>().RelationshipDefCol["<<|=RELATIONSHIPNAME|>>"];
            Assert.AreEqual(DeleteParentAction.Prevent, relationshipDef.DeleteParentAction);
            //---------------Execute Test ----------------------
            try
            {
                <<|=#CLASSNAME|>>.MarkForDelete();
                <<|=#CLASSNAME|>>.Save();
                Assert.Fail("Should have thrown exception due to deletion prevention");
            }
            //---------------Test Result -----------------------
            catch (BusObjDeleteException ex)
            {
                StringAssert.Contains("You cannot delete <<|=CLASSNAME|>> identified by ", ex.Message);
                StringAssert.Contains("via the <<|=RELATIONSHIPNAME|>> relationship", ex.Message);
            }
        }
        |>>
        |>>
        |>>
        |>>
        
        <<|-- NOTE: DereferenceRelated in this test could fail if the related property is compulsory --|>>
        <<|FOREACH(Relationships):
        <<|IF(GenerateCode):
        <<|IF(IsMultiple):
        <<|IF(!DeleteParentAction EQUALS "Prevent"):
        <<|IF(DeleteParentAction EQUALS "DeleteRelated"):
        |>>
        <<|IF(DeleteParentAction EQUALS "DereferenceRelated"):
        [Test, Ignore("Does not apply for single relationships.")]  // Checks that deleting a parent clears the related property on the child
        |>>
        <<|IF(DeleteParentAction EQUALS "DoNothing"):
        [Test]  // Deletes the parent but leaves the child
        |>>
        public void Test_MultipleRelationshipDeletion_<<|=DELETEPARENTACTION|>>_<<|=RELATIONSHIPNAME|>>()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = TestUtils<<|=CLASSNAME|>>.CreateSaved<<|=CLASSNAME|>>();

            <<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>> boForRelationship<<|=RELATIONSHIPNAME|>> = TestUtils<<|=RELATEDCLASS|>>.CreateUnsavedValid<<|=RELATEDCLASS|>>();
            boForRelationship<<|=RELATIONSHIPNAME|>>.<<|=RELATEDPROPERTYNAME|>> = <<|=#CLASSNAME|>>.<<|=PROPERTYNAME|>>;
            boForRelationship<<|=RELATIONSHIPNAME|>>.Save();

            //---------------Assert Preconditions---------------
            Assert.AreEqual(1, <<|=#CLASSNAME|>>.<<|=RELATIONSHIPNAME|>>.Count);
            IRelationshipDef relationshipDef = ClassDef.Get<<<|=CLASSNAME|>>>().RelationshipDefCol["<<|=RELATIONSHIPNAME|>>"];
            Assert.AreEqual(DeleteParentAction.<<|=DELETEPARENTACTION|>>, relationshipDef.DeleteParentAction);
            //---------------Execute Test ----------------------
            <<|=#CLASSNAME|>>.MarkForDelete();
            <<|=#CLASSNAME|>>.Save();
            //---------------Execute Test ----------------------
            BusinessObjectManager.Instance.ClearLoadedObjects();
            GC.Collect();
            TestUtilsShared.WaitForGC();

            try
            {
                Broker.GetBusinessObject<<<|=CLASSNAME|>>>(<<|=#CLASSNAME|>>.ID);
                Assert.Fail("BO should no longer exist and exception should be thrown");
            }
            catch (BusObjDeleteConcurrencyControlException ex)
            {
                StringAssert.Contains("There are no records in the database for the Class: <<|=CLASSNAME|>>", ex.Message);
            }            
            
            <<|IF(DeleteParentAction EQUALS "DeleteRelated"):
            try
            {
                Broker.GetBusinessObject<<<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>>>(boForRelationship<<|=RELATIONSHIPNAME|>>.ID);
                Assert.Fail("BO should no longer exist and exception should be thrown");
            }
            catch (BusObjDeleteConcurrencyControlException ex)
            {
                StringAssert.Contains("There are no records in the database for the Class: <<|=RELATEDCLASS|>>", ex.Message);
            }
            |>>
            <<|IF(DeleteParentAction EQUALS "DereferenceRelated"):
            <<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>> relatedBO = Broker.GetBusinessObject<<<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>>>(boForRelationship<<|=RELATIONSHIPNAME|>>.ID);
            Assert.IsNull(relatedBO.<<|=RELATEDPROPERTYNAME|>>);
            |>>
            <<|IF(DeleteParentAction EQUALS "DoNothing"):
            <<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>> relatedBO = Broker.GetBusinessObject<<<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>>>(boForRelationship<<|=RELATIONSHIPNAME|>>.ID);
            Assert.AreEqual(boForRelationship<<|=RELATIONSHIPNAME|>>, relatedBO);
            |>>
        }
        |>>
        |>>
        |>>
        |>>       
        
        <<|-- This test template could be combined into the one below if there was an OR function --|>>
        <<|-- TODO: this is not working, especially for in-memory DB
        <<|FOREACH(Relationships):
        <<|IF(GenerateCode):
        <<|IF(!IsMultiple):
        <<|IF(DeleteParentAction EQUALS "Prevent"):
        [Test]  // Checks that deletion is prevented when a child exists
        public void Test_SingleRelationshipDeletion_PreventDelete_<<|=RELATIONSHIPNAME|>>()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = TestUtils<<|=CLASSNAME|>>.CreateUnsavedValid<<|=CLASSNAME|>>();

            <<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>> boForRelationship<<|=RELATIONSHIPNAME|>> = TestUtils<<|=RELATEDCLASS|>>.CreateSaved<<|=RELATEDCLASS|>>();
            <<|=#CLASSNAME|>>.<<|=RELATIONSHIPNAME|>> = boForRelationship<<|=RELATIONSHIPNAME|>>;
            <<|=#CLASSNAME|>>.Save();

            //---------------Assert Preconditions---------------
            IRelationshipDef relationshipDef = ClassDef.Get<<<|=CLASSNAME|>>>().RelationshipDefCol["<<|=RELATIONSHIPNAME|>>"];
            Assert.AreEqual(DeleteParentAction.Prevent, relationshipDef.DeleteParentAction);
            //---------------Execute Test ----------------------
            try
            {
                <<|=#CLASSNAME|>>.MarkForDelete();
                <<|=#CLASSNAME|>>.Save();
                Assert.Fail("Should have thrown exception due to deletion prevention");
            }
            //---------------Test Result -----------------------
            catch (BusinessObjectReferentialIntegrityException ex)
            {
                StringAssert.Contains("Cannot delete this '<<|=CLASSNAME|>>' for the following reasons:", ex.Message);
            }
        }
        |>>
        |>>
        |>>
        |>>
        --|>>
        
        <<|-- NOTE: DereferenceRelated in this test could fail if the related property is compulsory --|>>
        <<|FOREACH(Relationships):
        <<|IF(GenerateCode):
        <<|IF(!IsMultiple):
        <<|IF(!DeleteParentAction EQUALS "Prevent"):
        <<|IF(DeleteParentAction EQUALS "DeleteRelated"):
        [Test]  // Checks that deleting a parent deletes the child
        |>>
        <<|IF(DeleteParentAction EQUALS "DereferenceRelated"):
        [Test]  // Checks that child is deleted. Dereferencing is done by setting the child's foreign key to null, but the child is deleted, so no further testing is required.
        |>>
        <<|IF(DeleteParentAction EQUALS "DoNothing"):
        [Test]  // Checks that deleting this instance has no effect in the related class
        |>>
        public void Test_SingleRelationshipDeletion_<<|=DELETEPARENTACTION|>>_<<|=RELATIONSHIPNAME|>>()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = TestUtils<<|=CLASSNAME|>>.CreateUnsavedValid<<|=CLASSNAME|>>();

            <<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>> boForRelationship<<|=RELATIONSHIPNAME|>> = TestUtils<<|=RELATEDCLASS|>>.CreateUnsavedValid<<|=RELATEDCLASS|>>();
            <<|=#CLASSNAME|>>.<<|=RELATIONSHIPNAME|>> = boForRelationship<<|=RELATIONSHIPNAME|>>;
            <<|=#CLASSNAME|>>.Save();

            //---------------Assert Preconditions---------------
            IRelationshipDef relationshipDef = ClassDef.Get<<<|=CLASSNAME|>>>().RelationshipDefCol["<<|=RELATIONSHIPNAME|>>"];
            Assert.AreEqual(DeleteParentAction.<<|=DELETEPARENTACTION|>>, relationshipDef.DeleteParentAction);
            //---------------Execute Test ----------------------
            <<|=#CLASSNAME|>>.MarkForDelete();
            <<|=#CLASSNAME|>>.Save();
            //---------------Execute Test ----------------------
            BusinessObjectManager.Instance.ClearLoadedObjects();
            GC.Collect();
            TestUtilsShared.WaitForGC();

            try
            {
                Broker.GetBusinessObject<<<|=CLASSNAME|>>>(<<|=#CLASSNAME|>>.ID);
                Assert.Fail("BO should no longer exist and exception should be thrown");
            }
            catch (BusObjDeleteConcurrencyControlException ex)
            {
                StringAssert.Contains("There are no records in the database for the Class: <<|=CLASSNAME|>>", ex.Message);
            }            
            
            <<|IF(DeleteParentAction EQUALS "DeleteRelated"):
            try
            {
                Broker.GetBusinessObject<<<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>>>(boForRelationship<<|=RELATIONSHIPNAME|>>.ID);
                Assert.Fail("BO should no longer exist and exception should be thrown");
            }
            catch (BusObjDeleteConcurrencyControlException ex)
            {
                StringAssert.Contains("There are no records in the database for the Class: <<|=RELATEDCLASS|>>", ex.Message);
            }
            |>>
            <<|IF(DeleteParentAction EQUALS "DoNothing"):
            <<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>> relatedBO = Broker.GetBusinessObject<<<|=RELATEDASSEMBLY|>>.<<|=RELATEDCLASS|>>>(boForRelationship<<|=RELATIONSHIPNAME|>>.ID);
            Assert.AreEqual(relatedBO.ID.ToString(),boForRelationship<<|=RELATIONSHIPNAME|>>.ID.ToString());
            |>>
            
        }
        |>>
        |>>
        |>>
        |>>
       
        <<|IF(HasSuperClass):
        [Test]  <<|-- TODO: watch out for these tests now that discriminator is supported on other inheritance types --|>>
        public void Test_Inheritance_SuperClassDef_PropertiesCorrect()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            ISuperClassDef superClassDef = ClassDef.Get<<<|=CLASSNAME|>>>().SuperClassDef;
            //---------------Test Result -----------------------
            Assert.AreEqual("<<|=SuperClassName|>>", superClassDef.ClassName);
            Assert.AreEqual("<<|=SuperClassAssemblyName|>>", superClassDef.AssemblyName);
            <<|IF(InheritanceType EQUALS "ClassTableInheritance"):
            <<|IF(SuperClassDefIDIsNull):Assert.IsNull(superClassDef.ID);|>>
            <<|IF(!SuperClassDefIDIsNull):Assert.AreEqual("<<|=SuperClassChildID|>>", superClassDef.ID);|>>
            |>>
            <<|IF(InheritanceType EQUALS "SingleTableInheritance"):
            Assert.AreEqual("<<|=SuperClassDiscriminator|>>", superClassDef.Discriminator);
            |>>
        }
		
		<<|IF(InheritanceType EQUALS "ClassTableInheritance"):
        [Test]
        public void Test_Inheritance_SuperClassDef_RelatedClassIsCorrect()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------

            IClassDef classDef = ClassDef.Get<<<|=CLASSNAME|>>>();
            ISuperClassDef superClassDef = classDef.SuperClassDef;
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            IClassDef relatedClassDef = ClassDef.ClassDefs[superClassDef.AssemblyName, superClassDef.ClassName];
            //---------------Test Result -----------------------
            Assert.IsNotNull(relatedClassDef);
            <<|IF(SuperClassDefIDIsEmpty):  <<|-- Can't replicate this with Firestarter right now --|>>
			Assert.IsNull(classDef.PrimaryKeyDef, "For empty string ID parameter, the child has no primary key and uses the inherited parent's primary key as its own");
			IPropDef relatedPrimaryKeyDef = relatedClassDef.PrimaryKeyDef[0];
			Assert.IsNotNull(relatedPrimaryKeyDef);
            |>>
            <<|IF(SuperClassDefIDIsNotNullOrEmpty):
            IPropDef propDef = classDef.PropDefcol[superClassDef.ID];
            Assert.IsNotNull(propDef);
            IPropDef relatedPrimaryKeyDef = relatedClassDef.PrimaryKeyDef[0];
            Assert.IsNotNull(relatedPrimaryKeyDef);
            Assert.AreEqual(propDef.PropertyType, relatedPrimaryKeyDef.PropertyType);
            |>>
            <<|IF(SuperClassDefIDIsNull):  <<|-- Can't replicate this with Firestarter right now --|>>
            IPropDef relatedPrimaryKeyDef = relatedClassDef.PrimaryKeyDef[0];
            Assert.IsNotNull(relatedPrimaryKeyDef);
            IPropDef propDef = classDef.PropDefColIncludingInheritance[relatedPrimaryKeyDef.PropertyName];
            Assert.IsNotNull(propDef, "Where no child ID match has been specified, the child must have a property with the same name and type as the parent ID");
            Assert.AreEqual(propDef.PropertyType, relatedPrimaryKeyDef.PropertyType);
            |>>
        }
        |>>
        
        <<|IF(InheritanceType EQUALS "SingleTableInheritance"):
        [Test]
        public void Test_Inheritance_SuperClassDef_RelatedClassIsCorrect()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------

            IClassDef classDef = ClassDef.Get<<<|=CLASSNAME|>>>();
            ISuperClassDef superClassDef = classDef.SuperClassDef;
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            IClassDef relatedClassDef = ClassDef.ClassDefs[superClassDef.AssemblyName, superClassDef.ClassName];
            //---------------Test Result -----------------------
            Assert.IsNotNull(relatedClassDef);
            IPropDef propDef = relatedClassDef.PropDefcol[superClassDef.Discriminator];
            Assert.IsNotNull(propDef, "The discriminator must be a property on the parent class");
        }
        |>>
		
        [Test]
        public void Test_Inheritance_CodeClass_InheritsCorrectly()
        {
            CheckIfTestShouldBeIgnored();
            //---------------Set up test pack-------------------
            BORegistry.DataAccessor = new DataAccessorInMemory();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            <<|=CLASSNAME|>> <<|=#CLASSNAME|>> = TestUtils<<|=CLASSNAME|>>.CreateUnsavedValid<<|=CLASSNAME|>>();
            //---------------Test Result -----------------------
            Assert.IsInstanceOf(typeof(<<|=SuperClassAssemblyName|>>.<<|=SuperClassName|>>), <<|=#CLASSNAME|>>);
        }        
        |>>
    }
// ReSharper restore RedundantNameQualifier
// ReSharper restore InconsistentNaming
// ReSharper restore SuggestUseVarKeywordEvident

}
